本系列文章已出版實體書籍:
「你的地圖會說話?WebGIS 與 JavaScript 的情感交織」(博碩文化)
WebGIS啟蒙首選✖五家地圖API✖近百個程式範例✖實用簡易口訣✖學習難度分級✖補充ES6小知識
今天要來跟大家介紹環域查詢的前置作業。
使用者在圖台網站上想要查詢一塊區域內的資料,首先,
要先決定查詢的範圍可能是圓、長方形、不規則多邊形等等,
有兩種方式。
今天我們就要來使用Leaflet API來實現繪圖工具。
很久沒使用leaflet了,來幫大家複習一下。
↓ 先引入圖台基本的css與js
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
↓ 建一個存放地圖的div
<div id="lmap"></div>
↓ 今天附上簡易的css,存放地圖div的高度記得要設定,不然地圖會顯現不出來!
#lmap {
height: 100%;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
↓ 初始化地圖
var LMap = L.map(document.getElementById('lmap'), {
center: [23.5, 121], // 中心點
zoom: 7, // 縮放層級
crs: L.CRS.EPSG3857, // 座標系統
});
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
id: 'mapbox.streets'
}).addTo(LMap); // 新增底圖
Leaflet API有一個很不錯的繪圖工具,繪圖完成後可以直接畫好在地圖上,並且可以儲存、編輯、返回上一個繪圖動作。
↑ 繪圖工具
↑ 點擊
↑ 完成
↑ 返回上一個動作
↓ 引入繪圖的css與js
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.2/leaflet.draw.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.2/leaflet.draw.js"></script>
↓ 建立一個FeatureGroup,用以存放繪圖的圖資
var drawItem = new L.FeatureGroup();
LMap.addLayer(drawItem);
↓ 新增繪圖的控制項
var option = {
position: 'topleft',
collapsed: true,
edit: {
featureGroup: drawItem,
},
};
var drawControl = new L.Control.Draw(option);
LMap.addControl(drawControl);
↓ 新增繪圖的事件,在繪圖建立完的時候發生的callback function。
LMap.on(L.Draw.Event.CREATED, function (e) {
var layer = e.layer;
drawItem.addLayer(layer); // 必須將畫完的圖層加入
console.log(arguments);
});
// 另一種寫法,以字串的方式寫事件名稱
LMap.on('draw:created', function (e) {
var layer = e.layer;
console.log(arguments);
drawItem.addLayer(layer);
});
↓ Leaflet 繪圖事件一覽
↓ 讓我們來看看繪圖建立完成的callback function的arguments
↓ 可以找到layer,並利用layer的方法找到繪製的半徑與中心點座標。並用layerType判斷圖形是哪一種形狀。
LMap.on(L.Draw.Event.CREATED, function (e) {
var layer = e.layer;
var type = e.layerType;
drawItem.addLayer(layer);
console.log(type);
if (type === 'circle') {
var center = layer.getLatLng();
var radius = layer.getRadius();
console.log(`經度: ${center.lng}, 緯度: ${center.lat}`);
console.log(`半徑: ${radius} (m)`);
}
});
↓ 結果
↓ 如果今天針對不同種圖形,要做相對應的事情,就要用if...else...來判斷type
if (type === 'circle') {
var center = layer.getLatLng();
var radius = layer.getRadius();
console.log(`經度: ${center.lng}, 緯度: ${center.lat}`);
console.log(`半徑: ${radius} (m)`);
} else if (type === 'marker'){
var point = layer.getLatLng();
console.log(`經度: ${point.lng}, 緯度: ${point.lat}`);
} else if (type === 'rectangle'){
var str ="";
var arr = layer.getLatLngs();
arr = arr[0].forEach(function(item, index){
str += `${index} => 經度: ${item.lng}, 緯度: ${item.lat}`
});
console.log(str);
} else if (type === 'polygon'){
var str ="";
var arr = layer.getLatLngs();
arr = arr[0].map(function(item, index){
return{
x: item.lng,
y: item.lat
}
});
console.log(arr);
}
if...else...越寫越長,越寫越多,越寫越不直觀。有沒有什麼方法?在不寫if...else...的情況下來因應不同種的情形,
不但不寫判斷,還要讓每一個function獨立只作業一件事情。
下一篇及下下篇,要來跟大家介紹callback與promise,
並且用adapter design pattern(配接器)的設計模式,
來重新寫callback function!
並達到最簡化判斷式的效果。
最近每天上班寫程式處理雜事,下班寫程式寫文章,腦袋越來越容易打結QAQ